﻿using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Fuse8.DomainFramework.Common;
using Fuse8.DomainFramework.Domain;

namespace Fuse8.DomainFramework.DataAccess.SqlDatabase
{
	internal class AliasBuilder
	{		
		public const string DefaultEntityAlias = "p";

		public static string BuildAlias(Expression expression, string defaultAlias)
		{
			var expr = expression as MemberExpression;
			if (expression is ParameterExpression || expr == null)
			{
				return defaultAlias;
			}
			var propertyList = new List<string>();
			while (expr != null)
			{
				propertyList.Add(expr.Member.Name);
				expr = expr.Expression as MemberExpression;
			}
			propertyList.Reverse();
			return propertyList.Aggregate(defaultAlias, MakeAliasNode);
		}


		public static RelatedProperty BuildRelatedProperty (Expression expression)
		{
			return BuildRelatedProperty(expression, DefaultEntityAlias);
		}

		private static RelatedProperty BuildRelatedProperty(Expression expression, string parentAlias)
		{

			RelatedProperty root;
			BuildRelatedProperty(expression, parentAlias, out root);
			return root;
		}

		private static RelatedProperty BuildRelatedProperty(Expression expression, string parentAlias, out RelatedProperty root)
		{
			RelatedProperty rootNode;
			var expr = expression as MemberExpression;
			if (expression is ParameterExpression || expr == null)
			{
				return root = null;
			}
			var result = BuildRelatedProperty(expr.Expression, parentAlias, out rootNode);
			var innerProperty = new RelatedProperty { PropertyType = expr.Member.GetMemberType(), PropertyName = expr.Member.Name, Alias = MakeAliasNode(result != null ? result.Alias : parentAlias, expr.Member.Name) };
			if (result != null)
			{
				result.RelatedProperties = new RelatedPropertyCollection { innerProperty };
			}

			root = rootNode ?? innerProperty;
			return innerProperty;
		}

		private static string MakeAliasNode (string parentAlias, string propertyName)
		{
			return string.Format("{0}_{1}", parentAlias, propertyName);
		}

	}
}